#include "scenario_based_testing.h"

// 全局 RAII 包装器（定义）
SingletonRAII singletonGuard;

// 单例实例获取
MySelfScenarioBasedTesting& MySelfScenarioBasedTesting::getInstance() {
    static MySelfScenarioBasedTesting instance;
    return instance;
}

// 初始化软总线并监听套接字
int32_t MySelfScenarioBasedTesting::init() {
    std::cout << "init..." << std::endl;
    int32_t result = -1;
    result = MySelfAddPermission();
    if (0 != result) {
        std::cout << "MySelfAddPermission failed: " << result << std::endl;
        return result;
    }
    result = MySelfInitDeviceManager();
    if (0 != result) {
        std::cout << "MySelfInitDeviceManager failed: " << result << std::endl;
        return result;
    }
    result = MySelfGetLocalDeviceId();
    if (0 != result) {
        std::cout << "MySelfGetLocalDeviceId failed: " << result << std::endl;
        return result;
    }
    result = MySelfListening();
    if (0 != result) {
        std::cout << "MySelfListening failed: " << result << std::endl;
        return result;
    }
    startMessageProcessingThread();
    startMessageSendThread();
    return result;
}

// 资源清理（可选）
void MySelfScenarioBasedTesting::cleanup() {
    std::cout << "Cleaning up resources..." << std::endl;
    getInstance().stopMessageProcessingThread();
    getInstance().stopMessageSendThread();
    getInstance().MySelfUnInitDeviceManager();
    getInstance().MySelfShutdownSocket(getInstance().listeningSocket);
    getInstance().MySelfUnInitDeviceManager();
}

void MySelfScenarioBasedTesting::startMessageProcessingThread() {
    stopWorker = false;
    workerThread = std::thread(&MySelfScenarioBasedTesting::processMessages, this);
}

void MySelfScenarioBasedTesting::stopMessageProcessingThread() {
    stopWorker = true;
    queueCV.notify_all();
    if (workerThread.joinable()) {
        workerThread.join();
    }
}

void MySelfScenarioBasedTesting::startMessageSendThread() {
    sendStopWorker = false;
    sendThread = std::thread(&MySelfScenarioBasedTesting::processSendMessages, this);
}

void MySelfScenarioBasedTesting::stopMessageSendThread() {
    sendStopWorker = true;
    sendQueueCV.notify_all();
    if (sendThread.joinable()) {
        sendThread.join();
    }
}

// 根据 socket 返回消息
int32_t MySelfScenarioBasedTesting::mySelfSendMessage(int32_t socket, nlohmann::json json) {
    int32_t result = -1;
    std::string jsonStr = json.dump();
    const char* data = jsonStr.c_str();
    int32_t msgLen = jsonStr.size();
    std::cout << "msgLen: " << msgLen << std::endl;
    result = SendMessage(socket, data, msgLen);
    if (result != 0) {
        std::cout << "Send failed, result = " << result << std::endl;
    } else {
        std::cout << "Send success: " << data << std::endl;
    }
    return result;
}

// 获取并返回系统内存和CPU信息
void MySelfScenarioBasedTesting::getSystemInfo(int32_t socket, std::string method) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Succeed";
    response["method"] = method;
    
    // 获取内存总数
    std::string memCommand = "cat /proc/meminfo | grep MemTotal | cut -d\":\" -f2 | cut -d'k' -f1";
    auto [memOutput, memExit] = MySelfGetTerminalOutput(memCommand);
    std::cout << "Memory exit_code: " << memExit << std::endl;
    std::cout << "Memory result: " << memOutput.c_str() << std::endl;
    
    // 获取CPU核心数
    std::string cpuCommand = "cat /proc/cpuinfo | uniq | grep processor | wc -l";
    auto [cpuOutput, cpuExit] = MySelfGetTerminalOutput(cpuCommand);
    std::cout << "CPU exit_code: " << cpuExit << std::endl;
    std::cout << "CPU result: " << cpuOutput.c_str() << std::endl;
    
    // 构建响应数据
    nlohmann::json data;
    
    if (0 == memExit) {
        // 移除换行符
        memOutput.erase(std::remove(memOutput.begin(), memOutput.end(), '\n'), memOutput.end());
        data["memTotalKB"] = std::stoi(memOutput);

    } else {
        data["memError"] = memOutput;
        response["code"] = -1;
    }
    
    if (0 == cpuExit) {
        // 移除换行符并转换为整数
        cpuOutput.erase(std::remove(cpuOutput.begin(), cpuOutput.end(), '\n'), cpuOutput.end());
        data["cpuCores"] = std::stoi(cpuOutput);
    } else {
        data["cpuError"] = cpuOutput;
        response["code"] = (response["code"] == 0) ? -2 : -3;
    }
    
    response["data"] = data;
    
    // 根据状态更新消息
    if (response["code"] != 0) {
        response["message"] = "Partial failure in system info retrieval";
    }
    std::lock_guard<std::mutex> lock(sendQueueMutex);
    sendQueue.push({socket, response});
    sendQueueCV.notify_one();
}

// 获取并返回软总线版本信息
void MySelfScenarioBasedTesting::getSoftbusVersion(int32_t socket, std::string method) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Succeed";
    response["method"] = method;
    
    std::string command = "begetctl dump api | grep DisplayVersion 2>/dev/null | cut -d\":\" -f2";
    auto [output, exit_code] = MySelfGetTerminalOutput(command);
    std::cout << "exit_code: " << exit_code << std::endl;
    std::cout << "Shell result: " << output.c_str() << std::endl;
    if (0 == exit_code) {
        response["version"] = output;
    } else {
        response["message"] = output;
    }
    response["code"] = exit_code;
    std::lock_guard<std::mutex> lock(sendQueueMutex);
    sendQueue.push({socket, response});
    sendQueueCV.notify_one();
}

//一键设备重启
void MySelfScenarioBasedTesting::rebootDevice(int32_t socket, std::string method) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Reboot successfully";
    response["method"] = method;
    
    std::string command = "reboot";
    std::cout << "waiting for reboot" << std::endl;
    auto [output, exit_code] = MySelfGetTerminalOutput(command);
    std::cout << "Reboot command exit_code: " << exit_code << std::endl;
    std::cout << "Reboot command output: " << output.c_str() << std::endl;
    
    if (0 != exit_code) {
        response["code"] = exit_code;
        response["message"] = "Failed to reboot device: " + output;
        std::lock_guard<std::mutex> lock(sendQueueMutex);
        sendQueue.push({socket, response});
        sendQueueCV.notify_one();
    }
}

//获取可拉起应用清单
void MySelfScenarioBasedTesting::getPullUpAppList(int32_t socket, std::string method) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Succeed";
    response["method"] = method;
    
    // 获取应用列表
    std::string command = "cat /data/applist.txt";
    auto [output, exit_code] = MySelfGetTerminalOutput(command);
    std::cout << "exit_code: " << exit_code << std::endl;
    std::cout << "Shell result: " << output << std::endl;
    
    if (0 == exit_code) {
        // 解析应用列表数据
        nlohmann::json appList = nlohmann::json::array();
        
        // 按行分割输出
        std::istringstream iss(output);
        std::string line;
        
        while (std::getline(iss, line)) {
            // 移除行尾换行符
            if (!line.empty() && line.back() == '\n') {
                line.pop_back();
            }
            if (!line.empty() && line.back() == '\r') {
                line.pop_back();
            }
            
            // 检查是否符合预期格式
            if (line.find("aa start") != std::string::npos) {
                // 改进的解析逻辑：处理带引号和不带引号的情况
                std::string bundle;
                std::string ability;
                
                // 提取 -b 参数值
                std::size_t bPos = line.find("-b ");
                if (bPos != std::string::npos) {
                    bPos += 3; // 跳过 "-b "
                    std::size_t bEnd = line.find(' ', bPos);
                    if (bEnd == std::string::npos) bEnd = line.length();
                    
                    bundle = line.substr(bPos, bEnd - bPos);
                    
                    // 移除可能存在的引号
                    if (!bundle.empty() && bundle.front() == '"') 
                        bundle.erase(0, 1);
                    if (!bundle.empty() && bundle.back() == '"') 
                        bundle.pop_back();
                }
                
                // 提取 -a 参数值
                std::size_t aPos = line.find("-a ");
                if (aPos != std::string::npos) {
                    aPos += 3; // 跳过 "-a "
                    std::size_t aEnd = line.find(' ', aPos);
                    if (aEnd == std::string::npos) aEnd = line.length();
                    
                    ability = line.substr(aPos, aEnd - aPos);
                    
                    // 移除可能存在的引号
                    if (!ability.empty() && ability.front() == '"') 
                        ability.erase(0, 1);
                    if (!ability.empty() && ability.back() == '"') 
                        ability.pop_back();
                }
                
                // 如果成功提取到 bundle 和 ability
                if (!bundle.empty() && !ability.empty()) {
                    appList.push_back({
                        {"name", bundle},
                        {"mainAbility", ability}
                    });
                    
                    std::cout << "Found app: bundle=" << bundle 
                              << ", ability=" << ability << std::endl;
                }
            }
        }
        
        response["list"] = appList;
    } else {
        response["message"] = output.empty() ? "Failed to get app list" : output;
        response["code"] = exit_code;
    }
    
    // 调试输出
    // std::cout << "Sending response: " << response.dump() << std::endl;
    
    std::lock_guard<std::mutex> lock(sendQueueMutex);
    sendQueue.push({socket, response});
    sendQueueCV.notify_one();
}

// 新增方法：拉起指定应用
void MySelfScenarioBasedTesting::pullUpTheApplication(int32_t socket, std::string method, nlohmann::json jsonData) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Succeed";
    response["method"] = method;
    
    // 检查参数是否完整
    if (!jsonData.contains("name") || !jsonData.contains("mainAbility")) {
        response["code"] = -1;
        response["message"] = "Missing parameters: name or mainAbility";
        std::lock_guard<std::mutex> lock(sendQueueMutex);
        sendQueue.push({socket, response});
        sendQueueCV.notify_one();
        return;
    }
    
    try {
        // 获取参数值
        std::string bundleName = jsonData["name"].get<std::string>();
        std::string mainAbility = jsonData["mainAbility"].get<std::string>();
        
        // 构造启动命令（带引号确保特殊字符正确处理）
        std::string command = "aa start -a \"" + mainAbility + "\" -b \"" + bundleName + "\"";
        std::cout << "Executing: " << command << std::endl;
        
        // 执行启动命令
        auto [output, exit_code] = MySelfGetTerminalOutput(command);
        std::cout << "Start app exit_code: " << exit_code << std::endl;
        std::cout << "Start app output: " << output << std::endl;
        
        // 处理结果
        if (0 != exit_code) {
            response["code"] = exit_code;
            response["message"] = "Failed to start app: " + output;
        } else {
            response["message"] = "App started successfully";
        }
    } catch (const nlohmann::json::exception& e) {
        response["code"] = -2;
        response["message"] = "JSON parsing error: " + std::string(e.what());
    } catch (...) {
        response["code"] = -3;
        response["message"] = "Unknown error occurred";
    }
    
    std::lock_guard<std::mutex> lock(sendQueueMutex);
    sendQueue.push({socket, response});
    sendQueueCV.notify_one();
}

// 修改设备名称
void MySelfScenarioBasedTesting::setDeviceName(int32_t socket, std::string method, nlohmann::json jsonData) {
    nlohmann::json response;
    response["code"] = 0;
    response["message"] = "Succeed";
    response["method"] = method;
    
    // 检查参数是否完整
    if (!jsonData.contains("value")) {
        response["code"] = -1;
        response["message"] = "Missing parameter: value";
        std::lock_guard<std::mutex> lock(sendQueueMutex);
        sendQueue.push({socket, response});
        sendQueueCV.notify_one();
        return;
    }
    
    try {
        // 获取设备名称值
        std::string deviceName = jsonData["value"].get<std::string>();
        
        // 构造 SQL 命令（使用单引号转义）
        std::string command = "sqlite3 /data/app/el2/0/database/com.ohos.settingsdata/entry/rdb/settingsdata.db "
                              "\"UPDATE 'SETTINGSDATA' SET VALUE = '" + deviceName + 
                              "' WHERE KEYWORD = 'settings.general.device_name'\"";
        
        std::cout << "Executing SQL command: " << command << std::endl;
        
        // 执行命令
        auto [output, exit_code] = MySelfGetTerminalOutput(command);
        std::cout << "SQL command exit_code: " << exit_code << std::endl;
        std::cout << "SQL command output: " << output << std::endl;
        
        // 处理结果
        if (0 != exit_code) {
            response["code"] = exit_code;
            response["message"] = "Failed to set device name: " + output;
        } else {
            response["message"] = "Device name set to: " + deviceName;
        }
    } catch (const nlohmann::json::exception& e) {
        response["code"] = -2;
        response["message"] = "JSON parsing error: " + std::string(e.what());
    } catch (const std::exception& e) {
        response["code"] = -3;
        response["message"] = "Error: " + std::string(e.what());
    }
    
    std::lock_guard<std::mutex> lock(sendQueueMutex);
    sendQueue.push({socket, response});
    sendQueueCV.notify_one();
}

// Message 请求分发函数
int32_t MySelfScenarioBasedTesting::handleMessage(MySelfScenarioBasedTesting::Message msg) {
    int32_t result = -1;
    std::string method = "";
    nlohmann::json jsonData;
    // 在这里处理消息（可以是解析、分发、回调等）
    std::string receivedMsg(msg.data.begin(), msg.data.end());
    std::cout << "Received message from socket " << msg.socket << ": " << receivedMsg << std::endl;
    try {
        jsonData = nlohmann::json::parse(receivedMsg);
    } catch (const nlohmann::json::parse_error& e) {
        result = -1;
        std::cerr << "json parse error: " << e.what() << std::endl;
        return result;
    }
    if (jsonData.contains("method") && jsonData["method"].is_string()) {
        method = jsonData["method"];
    } else {
        result = -1;
        std::cerr << "missing method name" << std::endl;
        return result;
    }

    if (method == "get_softbus_version") {
        getSoftbusVersion(msg.socket, method);
    } else if (method == "get_system_info") {        
        getSystemInfo(msg.socket, method);    
    } else if (method == "reboot_device") {
        rebootDevice(msg.socket, method);
    } else if (method == "get_pull_up_list") {
        getPullUpAppList(msg.socket, method);
    } else if (method == "pull_up_the_application") {
        pullUpTheApplication(msg.socket, method, jsonData);
    } else if (method == "set_device_name") {
        setDeviceName(msg.socket, method, jsonData);
    }
     else {
        // default case
    }
    return result;
}

void MySelfScenarioBasedTesting::processMessages() {
    while (!stopWorker) {
        std::unique_lock<std::mutex> lock(queueMutex);
        queueCV.wait(lock, [this] { return !messageQueue.empty() || stopWorker; });

        if (stopWorker) break;

        Message msg = std::move(messageQueue.front());
        messageQueue.pop();
        lock.unlock();
        // 示例：调用实际处理函数
        handleMessage(msg);
    }
}

void MySelfScenarioBasedTesting::processSendMessages() {
    while (!sendStopWorker) {
        std::unique_lock<std::mutex> lock(sendQueueMutex);
        sendQueueCV.wait(lock, [this] { return !sendQueue.empty() || sendStopWorker; });

        if (sendStopWorker) break;

        ReturnMessage msg = std::move(sendQueue.front());
        sendQueue.pop();
        mySelfSendMessage(msg.socket, msg.jsonData);
        lock.unlock();
    }
}

void MySelfScenarioBasedTesting::OnMessage(int32_t socket, const void* data, uint32_t len) {
    std::cout << "OnMessage socket: " << socket << std::endl;
    MySelfScenarioBasedTesting& instance = MySelfScenarioBasedTesting::getInstance();

    std::lock_guard<std::mutex> lock(instance.queueMutex);
    instance.messageQueue.push({
        socket,
        std::vector<uint8_t>((const uint8_t*)data, (const uint8_t*)data + len),
        len
        });
    instance.queueCV.notify_one();  // 唤醒工作线程
}

const char* GetUpdateRecvPath() {
    return "/data/";
}

void MySelfScenarioBasedTesting::OnFile(int32_t socket, FileEvent *event) {
    std::cout << "socket: " << socket << std::endl;
    std::cout << "event type: " << event->type << std::endl;
    // 绑定文件套接字时必须有如下设置本地存放位置相关逻辑，否则会绑定失败
    if (FILE_EVENT_RECV_UPDATE_PATH == event->type) {
        event->UpdateRecvPath = GetUpdateRecvPath;
        std::cout << "OnFile FILE_EVENT_RECV_UPDATE_PATH" << std::endl;
    } else {
        std::cout << "OnFile bytesProcessed = " << event->bytesProcessed << "bytesTotal = " << event->bytesTotal << std::endl;
    }
    // 接收成功
    if (FILE_EVENT_RECV_FINISH == event->type) {
        getInstance().MySelfShutdownSocket(socket);
        std::cout << "Shutdown socket: " << socket << std::endl;
    }

}

// RAII 包装器实现
SingletonRAII::SingletonRAII() {
    struct sigaction sa;
    sa.sa_handler = SingletonRAII::signalHandler;  // 使用静态函数
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    // 注册信号处理
    sigaction(SIGINT,  &sa, nullptr);  // Ctrl+C
    sigaction(SIGTERM, &sa, nullptr);  // kill -15
}

// 静态成员函数实现
void SingletonRAII::signalHandler(int signal) {
    const char* name = (signal == SIGINT) ? "SIGINT" :
                       (signal == SIGTERM) ? "SIGTERM" : "Unknown";
    std::cout << name << " detected, cleaning up..." << std::endl;
    MySelfScenarioBasedTesting::cleanup();
    std::exit(EXIT_SUCCESS);
}

SingletonRAII::~SingletonRAII() {
    // 析构时无需额外操作（单例会随程序退出自动析构）
}

// 批量添加需要的权限
int32_t MySelfScenarioBasedTesting::MySelfAddPermission() {
    int32_t result = -1;
    uint64_t tokenId = 0;
    const char *perms[2];
    perms[0] = OHOS_PERMISSION_DISTRIBUTED_SOFTBUS_CENTER;
    perms[1] = OHOS_PERMISSION_DISTRIBUTED_DATASYNC;
    NativeTokenInfoParams infoInstance = {
        .dcapsNum = 0,
        .permsNum = 2,
        .aclsNum = 0,
        .dcaps = NULL,
        .perms = perms,
        .acls = NULL,
        .processName = "dsoftbus_service",
        .aplStr = "system_core",
    };
    tokenId = GetAccessTokenId(&infoInstance);
    std::cout << "GetAccessTokenId: " << tokenId << std::endl;
    result = SetSelfTokenID(tokenId);
    return result;
}

// DmInitCallback 中对应的虚函数具体实现回调
void MySelfScenarioBasedTestingCallBack::OnRemoteDied() {
    std::cout << "OnRemoteDied" << std::endl;
    return;
}

// 初始化 DM 实例
int32_t MySelfScenarioBasedTesting::MySelfInitDeviceManager() {
    int32_t result = -1;
    std::shared_ptr<OHOS::DistributedHardware::DmInitCallback> initDMCallback = std::make_shared<MySelfScenarioBasedTestingCallBack>();
    result = OHOS::DistributedHardware::DeviceManager::GetInstance().InitDeviceManager(pkgName, initDMCallback);
    std::cout << "InitDeviceManager result: " << result << std::endl;
    return result;
}

// 释放 DM 实例
int32_t MySelfScenarioBasedTesting::MySelfUnInitDeviceManager() {
    int32_t result = -1;
    result = OHOS::DistributedHardware::DeviceManager::GetInstance().UnInitDeviceManager(this->pkgName);
    std::cout << "UnInitDeviceManager result: " << result << std::endl;
    return result;
}

// 获取 DM 软总线设备 ID
int32_t MySelfScenarioBasedTesting::MySelfGetLocalDeviceId() {
    int32_t result = -1;
    std::string deviceId = "";
    result = OHOS::DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceId(pkgName, deviceId);
    std::cout << "GetLocalDeviceId result: " << result << std::endl;
    sessionName = std::string("IShareListen_") + deviceId;
    std::cout << "GetLocalDeviceId sessionName: " << sessionName.c_str() << std::endl;
    return result;
}

// 监听特定缺省参数的通用套接字
int32_t MySelfScenarioBasedTesting::MySelfListening() {
    int32_t result = -1;
    uint32_t qosCount = 1;
    SocketInfo info = { 0 };
    info.name = const_cast<char*>(sessionName.c_str());
    info.pkgName = const_cast<char*>(pkgName.c_str());
    listeningSocket = Socket(info);
    if (listeningSocket < 0) {
        std::cout << "Socket create failed" << std::endl;
        return result;
    }
    listener = {
        .OnBind = OnBind,
        .OnShutdown = OnShutdown,
        .OnMessage = OnMessage,
        .OnFile = OnFile
    };
    QosTV qos[] = {
        {.qos = QOS_TYPE_MAX_LATENCY, .value = 100000},
    };
    result = Listen(listeningSocket, qos, qosCount, &listener);
    std::cout << "Listen result: " << result << std::endl;
    return result;
}

// 通过 socket 关闭套接字
void MySelfScenarioBasedTesting::MySelfShutdownSocket(int32_t socket) {
    if (socket > 0) {
        Shutdown(socket);
        std::cout << "Shutdown socket " << socket << " success" << std::endl;
    }
    return;
}

// 执行 shell 命令并回去返回值和输出打印
std::pair<std::string, int> MySelfScenarioBasedTesting::MySelfGetTerminalOutput(const std::string& command) {
    std::string output_str = "";
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        return {"Error: Failed to create pipe", -1};
    }

    pid_t pid = fork();
    if (pid == -1) {
        close(pipefd[0]);
        close(pipefd[1]);
        return {"Error: Failed to fork", -1};
    }

    if (pid == 0) { // 子进程
        close(pipefd[0]); // 关闭读端
        dup2(pipefd[1], STDOUT_FILENO); // 重定向 stdout 到管道
        close(pipefd[1]);
        execl("/bin/sh", "sh", "-c", command.c_str(), nullptr);
        exit(EXIT_FAILURE); // 如果 exec 失败
    } else { // 父进程
        close(pipefd[1]); // 关闭写端
        std::string result;
        char buffer[128] = { 0 };
        ssize_t bytesRead;
        while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
            result.append(buffer, bytesRead);
        }
        if (!result.empty()) {
            if (result.back() == '\n') {
                result.pop_back();
                if (!result.empty() && result.back() == '\r') {
                    result.pop_back();
                }
            }
        }
        close(pipefd[0]);
        int status;
        waitpid(pid, &status, 0); // 等待子进程结束

        if (WIFEXITED(status)) {
            return {result, WEXITSTATUS(status)};
        } else {
            return {"Error: Command did not exit normally", -1};
        }
    }
}

